﻿using System.Collections.Generic;
using System.Timers;
using System.Linq;
using DC2010.Objects.Base;
using DC2010.Objects.Common;
using DC2010.Objects.Data;
using log4net;

namespace DC2010.Objects.Logic
{
    public class BaseLogic : BaseObject
    {

        /// <summary>
        /// Every instance can have different data. 
        /// 1. It is much simplier structure than info
        /// 2. Some properties can be used on both places 
        ///    - Info(as definition) and 
        ///    - Data(real value)
        /// 3. For example in Info id of creature will be VEXIRK but real ID ill take from
        /// Data and id will be VEXIRK_{GUID} which tells us of specific mob spawn. When saving 
        /// game only Data will be saved, Gfx and Info are on definition level and no change will
        /// occur there.
        /// </summary>
        public BaseData Data { get; set; }
		
		//object life
		public virtual void Start() {}
		public virtual void Stop() {}
		public virtual void Pause() {}
		

        /// <summary>
        /// Log utility
        /// </summary>
        protected readonly ILog log = LogManager.GetLogger(typeof(BaseLogic));


        public virtual void Init()
        {
	        if (Data.Effects.Count > 0)
            {
			    if (!Root.I.CreatedTimers_objectIds.Contains(Data.Id))
				{
					Root.I.CreatedTimers_objectIds.Add(Data.Id);
				}
				
                Root.I.GlobalTimer.Elapsed += Timer_Elapsed;
            }	
        }

        void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            HandleConditionalEffects();
            HandleEffects();
        }

        /// <summary>
        /// Handle all effects where current object is owner.
        ///  
        /// Example:
        ///          Creature is owner of its items in inventory
        ///          Tile is owner of party standing on it
        ///          Item can be owner of other items (container, treasures)
        ///          Wall can be owner -> alcoves...
        /// 
        /// So ill find all item directly owned by current object. Process every effect. But im not looking for
        /// next level. Not looking for item items....etc. If player owns a treasure box ill handle effect on that item,
        /// but not on any item in that treasure box.
        /// 
        /// Main effect launcher is gamesystem. Launches in following tree:
        /// 
        /// - Map effects
        /// -------------
        ///   - Only for current level map???
        /// 
        /// - Tile effects on current level
        /// -------------------------------
        ///   - for example pits switching etc...
        /// 
        /// - Doors effects on current level
        /// --------------------------------
        ///   - Doors can close and open repeatively
        /// 
        /// - Items effects on current level (items owned by current level/map)
        /// -------------------------------------------------------------------
        ///   - not doing this
        ///    
        /// - Parties effects on current level
        /// ----------------------------------
        ///   - Party i party with hearoes and party with monsters
        ///   - movement, attacking, etc...
        /// 
        /// - Creatures effects on current level
        /// ------------------------------------
        ///   - Effect for single creature
        /// </summary>        
        public void HandleEffects()
        {
            List<BaseObject> ownedObjects = Root.I.GameSystem.GetOwnedObjects(Data.Id);

            foreach (BaseObject bo in ownedObjects)
            {
                if (bo is IEffected)
                {
                    //there can be an effect
                    IEffected ief = (IEffected) bo;
                    if ((ief.Effects!=null)&&(ief.Effects.Count>0))
                    {
                        foreach (KeyValue kv in ief.Effects)
                        {
                            EffectData ed = Root.I.EffectSystem.GetData(kv.Value);
                            ed.L.Pump(Data);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Handle all conditional effects where current object is owner. For desc. look up.
        /// </summary>
        public void HandleConditionalEffects()
        {
            List<BaseObject> ownedObjects = Root.I.GameSystem.GetOwnedObjects(Data.Id);

            foreach (BaseObject bo in ownedObjects)
            {
                if (bo is IConditioned)
                {
                    //there can be an effect
                    IConditioned ief = (IConditioned)bo;
                    if ((ief.Conditions != null) && (ief.Conditions.Count > 0))
                    {
                        foreach (KeyValue kv in ief.Conditions)
                        {
                            ConditionData ed = Root.I.ConditionSystem.GetData(kv.Value);
                            ed.L.CheckCondition(Data, null);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// A....
        /// </summary>
        /// <param name="e"></param>
        public void AssignEffect(EffectData e)
        {
            Data.Effects.Add(new KeyValue { Key = "id", Value = e.Id});
        }

        public void RemoveEffect(EffectData e)
        {
            var x = (from i in Data.Effects
                     where i.Value == e.Id
                     select i).FirstOrDefault();

            if (x != null)
                Data.Effects.Remove(x);
        }
    }
}
